#include <QtTest>

#include "../tests_common.h"

#include "bitwin/generic_bitwise.h"
#include "bitwin/generic_bitwise_templates.h"


Q_DECLARE_METATYPE(BitWin::PGenericBitwise)


using namespace BitWin;


class TestGenericBitwise: public QObject
{
    Q_OBJECT

private slots:

    void testBitwiseNoParam_data();
    void testBitwiseNoParam();

    void testBitwise_data();
    void testBitwise();

    void testHexDec_data();
    void testHexDec();
};


void TestGenericBitwise::testBitwiseNoParam_data()
{
    QTest::addColumn<PGenericBitwise>("indata");
    QTest::addColumn<QString>("outdata");
    
    QTest::newRow("16 bits, value 0")
        << GenericBitwise::fromIntegral<quint16>(0)
        << QString(16, '0')
    ;
    QTest::newRow("16 bits, value 1")
        << GenericBitwise::fromIntegral<quint16>(1)
        << (QString("1") + QString(15, '0'))
    ;
    QTest::newRow("16 bits, value 0xFADE")
        << GenericBitwise::fromIntegral<quint16>(0xFADE)
        << QString("0111101101011111")
    ;
    QTest::newRow("8 bits, value 0")
        << GenericBitwise::fromIntegral<quint8>(0)
        << QString(8, '0')
    ;
    QTest::newRow("8 bits, value 1")
        << GenericBitwise::fromIntegral<quint8>(1)
        << QString("10000000")
    ;
    QTest::newRow("8 bits, value 0xF1")
        << GenericBitwise::fromIntegral<quint8>(0xF1)
        << QString("10001111")
    ;
    
    QTest::newRow("Empty QString")
        << STRING_BITWISE(QString(""))
        << QString("")
    ;
    QTest::newRow("Null QString")
        << STRING_BITWISE(QString())
        << QString()
    ;
    QTest::newRow("QString, value 0xFADE")
        << STRING_BITWISE("0xFADE")
        << QString("0xFADE")
    ;
}

void TestGenericBitwise::testBitwiseNoParam()
{
    QFETCH(PGenericBitwise, indata);
    QFETCH(QString, outdata);
    
    QCOMPARE(indata->bitwise(), outdata);
}

void TestGenericBitwise::testBitwise_data()
{
    QTest::addColumn<PGenericBitwise>("indata");
    QTest::addColumn<BitRange>("range");
    QTest::addColumn<QString>("outdata");
    
    QTest::newRow("16 bits full range, value 0")
        << GenericBitwise::fromIntegral<quint16>(0)
        << BitRange(15, 0) << QString("0000000000000000")
    ;
    QTest::newRow("16 bits full range, value 1")
        << GenericBitwise::fromIntegral<quint16>(1)
        << BitRange(15, 0) << QString("1000000000000000")
    ;
    QTest::newRow("16 bits full range, value 0xF00D")
        << GenericBitwise::fromIntegral<quint16>(0xF00D)
        << BitRange(15, 0) << QString("1011000000001111")
    ;
    QTest::newRow("8 bits full range, value 1")
        << GenericBitwise::fromIntegral<quint8>(1)
        << BitRange(7, 0) << QString("10000000")
    ;
    QTest::newRow("8 bits full range, value 0xBA")
        << GenericBitwise::fromIntegral<quint8>(0xBA)
        << BitRange(7, 0) << QString("01011101")
    ;
    QTest::newRow("8 bits [6:2], value 0xCA")
        << GenericBitwise::fromIntegral<quint8>(0xCA)
        << BitRange(6, 2) << QString("  01001 ")
    ;
    QTest::newRow("8 bits [10:2], value 0xBA")
        << GenericBitwise::fromIntegral<quint8>(0xBA)
        << BitRange(10, 2) << QString("  011101")
    ;
    QTest::newRow("8 bits [12:10], value 0xBA")
        << GenericBitwise::fromIntegral<quint8>(0xBA)
        << BitRange(12, 10) << QString(8, ' ')
    ;
    QTest::newRow("16 bits null range")
        << GenericBitwise::fromIntegral<quint16>(0xF00D)
        << BitRange() << QString(16, ' ')
    ;
    
    QTest::newRow("Empty QString, range [12:10]")
        << STRING_BITWISE("")
        << BitRange(12, 10) << QString("")
    ;
    QTest::newRow("Null QString, range [12:10]")
        << STRING_BITWISE(QString())
        << BitRange(12, 10) << QString("")
    ;
    QTest::newRow("Null QString, null range ")
        << STRING_BITWISE(QString())
        << BitRange() << QString()
    ;
    QTest::newRow("QString, full range")
        << STRING_BITWISE("abcde")
        << BitRange(4, 0) << QString("abcde")
    ;
    QTest::newRow("QString, middle range")
        << STRING_BITWISE("abcde")
        << BitRange(3, 2) << QString("  cd ")
    ;
    QTest::newRow("QString, overrange")
        << STRING_BITWISE("abcde")
        << BitRange(7, 2) << QString("  cde")
    ;
}

void TestGenericBitwise::testBitwise()
{
    QFETCH(PGenericBitwise, indata);
    QFETCH(BitRange, range);
    QFETCH(QString, outdata);
    QCOMPARE(indata->bitwise(range), outdata);
}

void TestGenericBitwise::testHexDec_data()
{
    QTest::addColumn<PGenericBitwise>("indata");
    QTest::addColumn<QString>("hexdata");
    QTest::addColumn<QString>("decdata");
    
    QTest::newRow("16 bits value 0")
        << GenericBitwise::fromIntegral<quint16>(0)
        << QString("0x0") << QString("0")
    ;
    QTest::newRow("8 bits value 0")
        << GenericBitwise::fromIntegral<quint8>(0)
        << QString("0x0") << QString("0")
    ;
    QTest::newRow("16 bits value 1")
        << GenericBitwise::fromIntegral<quint16>(1)
        << QString("0x1") << QString("1")
    ;
    QTest::newRow("8 bits value 1")
        << GenericBitwise::fromIntegral<quint8>(1)
        << QString("0x1") << QString("1")
    ;
    QTest::newRow("32 bits")
        << GenericBitwise::fromIntegral<quint32>(0xC0D4F00D)
        << QString("0xc0d4f00d") << QString("3235180557")
    ;
    QTest::newRow("signed 16 bits value -2")
        << GenericBitwise::fromIntegral<qint16>(-2)
        << QString("0xfffe") << QString("-2")
    ;
    QTest::newRow("unsigned 16 bits value -2")
        << GenericBitwise::fromIntegral<quint16>(-2)
        << QString("0xfffe") << QString("65534")
    ;
}

void TestGenericBitwise::testHexDec()
{
    QFETCH(PGenericBitwise, indata);
    QFETCH(QString, hexdata);
    QFETCH(QString, decdata);
    QEXPECT_FAIL("signed 16 bits value -2", "QString::number quirk", Continue);
    QCOMPARE(indata->hex(), hexdata);
    QCOMPARE(indata->dec(), decdata);
}


QTEST_MAIN(TestGenericBitwise)


#include "main.moc"
